using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.IO;

namespace igp.net.DataModel
{
    /// <summary>
    /// This is an abstract class that is derived by all available items. 
    /// It defines some properties and methods that are necessary 
    /// for the items to react to user interactions and to draw properly on the screen.
    /// </summary>
    public abstract class IgpItem
    {
        /// <summary>
        /// Item name. This name is displayed in the item picker.
        /// </summary>
        public String ItemName { get; set; }

        /// <summary>
        /// This is an identifier of the item. It is used to uniquely identify an item.
        /// </summary>
        public int ItemID { get; protected internal set; }

        /// <summary>
        /// Contains information abut type of the item.
        /// </summary>
        public IgpItemType TypeID { get; protected set; }

        /// <summary>
        /// Gets/Sets item visibility on the screen.
        /// </summary>
        public bool IsVisible { get; set; }

        /// <summary>
        /// Gets/Sets item visibility on thr legend.
        /// </summary>
        public bool VisibleOnLegend { get; set; }

        /// <summary>
        /// Determines type of the line, which will be used to draw the item on the screen.
        /// </summary>
        public DashStyle LineType { get; set; }

        /// <summary>
        /// Here you have to draw yout item on the screen.
        /// </summary>
        /// <param name="graph">Graphics object you can use</param>
        public abstract void Draw(Graphics graph);

        /// <summary>
        /// Ges the X coordinare of a vector that starts where the mouse button was pressed and ends where the mouse is at the moment.
        /// Distance is measured in pixels.
        /// </summary>
        public int VectorX { get; private set; }

        /// <summary>
        /// Ges the Y coordinare of a vector that starts where the mouse button was pressed and ends where the mouse is at the moment.
        /// Distance is measured in pixels.
        /// </summary>
        public int VectorY { get; private set; }

        /// <summary>
        /// Gets/Sets color of the line, which is used to draw this item.
        /// </summary>
        public Color LineColor { get; set; }

        private int lineWidth;

        /// <summary>
        /// Gets/Sets width of the line, which is used to draw this item.
        /// </summary>
        public int LineWidth
        {
            get
            {
                return lineWidth;
            }
            set
            {
                if (value <= 0) throw new ArgumentException("Width must be positive!");
                lineWidth = value;
            }
        }

        /// <summary>
        /// Selects/Deselects the item.
        /// </summary>
        public bool IsSelected { get; set; }

        /// <summary>
        /// This method is required for item's reaction to mouse movement. 
        /// You must invoke this base method in your derived class in order 
        /// to update some useful properties.
        /// </summary>
        /// <param name="graph">Graphics object that can be used to paint something on the screen</param>
        /// <param name="e">Mouse Event Details</param>
        public virtual void InteractMove(Graphics graph, MouseEventArgs e)
        {
            MouseWhenMoving = e;
			
            if (MouseWhenPressed == null) return;
			
            VectorX = MouseWhenPressed.X - MouseWhenMoving.X;
            VectorY = MouseWhenPressed.Y - MouseWhenMoving.Y;
        }

        /// <summary>
        /// This method is required for item's reaction to mouse buttons being pressed. 
        /// You must invoke this base method in your derived class in order 
        /// to update some useful properties.
        /// </summary>
        /// <param name="graph">Graphics object that can be used to paint something on the screen</param>
        /// <param name="e">Mouse Event Details</param>
        public virtual void InteractDown(Graphics graph, MouseEventArgs e)
        {
            MouseWhenPressed = e;
        }

        /// <summary>
        /// This method is required for item's reaction to mouse buttons being released. 
        /// </summary>
        /// <param name="graph">Graphics object that can be used to paint something on the screen</param>
        /// <param name="e">Mouse Event Details</param>
        public virtual void InteractUp(Graphics graph, MouseEventArgs e)
        {
        }

        /// <summary>
        /// This method is used to save item's data.
        /// </summary>
        /// <param name="sw">A TextWriter object you can use</param>
        public virtual void SaveData(TextWriter sw) { }

        /// <summary>
        /// This method is used to load item's data.
        /// </summary>
        /// <param name="sr">A TextReader object you can use</param>
        public virtual void ReadData(TextReader sr) { }

        /// <summary>
        /// This property indicates that user interaction is being precessed by another item.
        /// You should not perform any actions that can collide with other items when this
        /// property is set to true.
        /// </summary>
        public static bool InteractionInUse { get; set; }

        /// <summary>
        /// Contains mouse details captured when a button was pressed.
        /// </summary>
        public MouseEventArgs MouseWhenPressed { get; private set; }

        /// <summary>
        /// Contains mouse details updated in real time when mouse is moved.
        /// </summary>
        public MouseEventArgs MouseWhenMoving { get; private set; }

        /// <summary>
        /// This constructor sets some properties. 
        /// It should be invoked in derived classes' constructors.
        /// </summary>
        protected IgpItem()
        {
            InteractionInUse = false;
            LineColor = Color.Red;
            LineWidth = 1;
            IsVisible = true;
            VisibleOnLegend = true;
        }
    }
}